Nessa análise buscaremos responder à dúvida quanto à existência ou não de uma ligação entre o IDH e índices relacionados e a incidência da pandemia de Covid-19 no estado do Rio de Janeiro. Os dados aqui utilizados estão disponíveis na Base dos Dados, de fonte principal do IBGE, no próprio site do IBGE e, no caso dos dados relacionados ao Covid, do site Brasil.io. Estes últimos são considerados quanto ao aspecto acumulado ao longo da pandemia, tendo sido extraídos no início da elaboração do trabalho, em 17/11/2021.
A escolha de realizar a análise quanto o estado do Rio de Janeiro se deu por os 3 integrantes do grupo serem fluminenses, de diferentes cidades, e nos interessava a possibilidade de fazer comparações.
import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.io as pio
import basedosdados as bd
import sqlite3 as sqlite
pio.renderers.default='notebook'
Para armazenar os dados espaciais que serão utilizados através do geopandas, nós optamos pelo spatialite. O arquivo abaixo, hospedado em forma de git, foi o script desenvolvido por nós para adquirir, através de um geojson, os dados e os inserir nesse tipo de banco.
Primeiramente, vamos ler nosso banco de dados que contém os dados da geografia, e criar uma tabela onde cada linha contém um ID de município e a sigla do estado ao qual esse município pertence, além de sua geometria.
dbpath = 'cities.db'
# Cria conexão e carrega a extensão do spatialite.
con = sqlite.connect(dbpath)
con.enable_load_extension(True)
con.execute('SELECT load_extension("mod_spatialite")')
# O GeoDataFrame somente adquire a geometria em hex.
sql = "SELECT id, sigla_uf, name, Hex(ST_AsBinary(geometry)) as geom FROM cities;"
cities = gpd.GeoDataFrame.from_postgis(sql, con, geom_col="geom")
# Limpando a base
RJ_data = cities[cities["sigla_uf"] == "RJ"].reset_index(drop=True)
RJ_data = RJ_data.astype({"id": int})
Temos que ler, agora, os dados relacionados à Covid. Esses dados foram retirados do site https://brasil.io/dataset/covid19/caso_full/ .
covid = pd.read_csv('caso_full.csv.gz', compression='gzip')
covid.rename(columns={"city_ibge_code": "id", "last_available_confirmed_per_100k_inhabitants": "cases_per_100k", "last_available_death_rate": "death_rate"}, inplace=True)
covid = covid[covid["id"] > 1000].astype({"id": int}) # Limpando a base que continha linhas com IDs inexistentes
covid_rj = covid[(covid["state"] == "RJ") & (covid["date"] == "2021-11-17")].reset_index(drop=True)
covid_rj = covid_rj[["id", "estimated_population", "cases_per_100k", "death_rate", "date", 'is_last']]
# Para animação
covid_fd = covid[(covid["state"] == "RJ")].reset_index(drop=True)
covid_fd = covid_fd[covid_fd["date"].str[-2:] == "01"] # Pegando apenas primeiro dia de cada mês
covid_fd = covid_fd[covid_fd["date"].str[:4] == "2021"] # Pegando apenas 2021
covid_fd = covid_fd[["id", "estimated_population", "cases_per_100k", "death_rate", "date", 'is_last']] # Pegando apenas colunas relevantes
covid_fd.head()
Novamente, com as tabelas prontas, basta dar merge e prepará-la para análises:
RJ_fulldata = pd.merge(RJ_data, covid_fd, on='id')
RJ_fulldata.sort_values(by = "date", inplace=True)
RJ_fulldata["date"] = RJ_fulldata["date"].astype('str')
Vamos, primeiramente, obter uma visão geral do panorama da pandemia
fig = px.choropleth(RJ_fulldata,
geojson = RJ_fulldata["geom"],
locations = RJ_fulldata.index,
color = "death_rate",
hover_name = "name",
hover_data = ["cases_per_100k", "death_rate", "estimated_population"],
labels = {
"cases_per_100k": "Cases per 100k habitants",
"death_rate": "Mortality rate",
"estimated_population": "Estimated population"
},
color_continuous_scale = "sunsetdark",
range_color=(0, 0.25),
animation_frame = 'date',
)
fig.update_geos( # Centralizando o mapa no RJ
projection=dict(
scale=55
),
center = dict(
lat=-22.208333,
lon=-42.896388
)
)
fig.update_layout(
title_text = "Taxa de mortalidade da Covid-19 ao longo dos meses de pandemia em 2021, por município",
margin={"r":0,"t":40,"l":0,"b":10}
)
fig.write_html("covid.html")
Por conta do peso do arquivo gerado, devido sua complexidade, o colocamos numa página externa. Portanto, acesse o dashbord interativo externo.
Iniciaremos a análise falando do próprio IDH, Índice de Desenvolvimento Humano, que é bastante conhecido, e leva em conta aspectos de expectativa de vida, educação e PIB per capita, disponibilizado quanto a cada município do país pelo IBGE. A última atualização deste foi no censo de 2010.
Começamos lendo o idh.csv e realizando uma junção com o RJ_data através dos nomes de municípios, já que o IBGE não disponibilizava os ids. Veja abaixo uma parcela do database:
idh = pd.read_csv('idh.csv')
RJ_idh = pd.merge(RJ_data, idh, on='name')
RJ_idh.head()
Agora que já temos os dados que nos interessam unificados, podemos iniciar a plotagem, utilizando os dados de geometria e através do plotly express. É possível observar que cidades da Região Metropolitana do estado possuem altos IDHs, como Niterói, enquanto a Região Serrana possui valores baixos, como por exemplo em Sumidouro. Veja abaixo a plotagem, em que é possível passar o mouse para ver informações:
fig = px.choropleth(RJ_idh,
geojson = RJ_idh["geom"],
locations = RJ_idh.index,
color = "IDH",
hover_name = "name",
color_continuous_scale = "Purples"
)
fig.update_geos(
projection=dict(
scale=55
),
center = dict(
lat=-22.208333,
lon=-42.896388
)
)
fig.update_layout(
title_text = "IDH de 2010, por município do RJ",
margin={"r":0,"t":50,"l":0,"b":50}
)
fig.show()
Análise da relação entre índices de educação e incidência do Covid-19 no estado do Rio de Janeiro
Temos interesse em realizar uma análise comparativa, então faremos a seguir um scatter plot relacionando a quantidade de mortes por Covid e o IDH, para podermos descobrir se há ou não uma correlação explícita. A escolha de fazer essa observação a partir das mortes, e não pela incidência da doença (número de casos) se dá pela quantidade de fatores que geram variabilidade nesta segunda, tornando a relação menos direta.
Por exemplo, municípios que investiram em testagem em massa certamente têm o número de casos inflados em relação a outros que testaram menos a população, não refletindo puramente a realidade. Analisando os óbitos, certamente nos deparamos com casos não notificados de morte por Covid, mas essa variação tende a ser melhor distibuída pelo estado, já que teoricamente depende menos de fatores externos
covid_idh = pd.merge(RJ_idh, covid_rj, on='id')
fig = px.scatter(covid_idh, x="death_rate", y="IDH", hover_data=['name'], trendline="ols",
color_discrete_sequence=['#734CB3'],trendline_color_override="orange",
title="Gráfico de dispersão entre taxa de mortalidade e IDH",
labels={"death_rate": "Taxa de mortalidade",
"name": "Município"})
fig.show()
Observe que o gráfico nos fornece uma distribuição desigual e aparentemente desordenada, que nos leva a acreditar que não há uma correlação direta entre os fatores. Niterói e Sumidouro, por exemplo, com respectivamente maior e menor IDH, não têm uma taxa de morte pela doença tão diferente. Traçamos uma reta de tendência, buscando analisar a disposição dos pontos e algum tipo de correlação entre os dados, mas a distância dos pontos à reta era tal que encontramos um baixíssimo $R^2$ (que pode ser observado passando o mouse pela reta, assim como para informações nos pontos).
Essa comparação nos indica que não há correlação clara entre o IDH de cada município e a incidência da pandemia de Covid-19. No entanto, conforme observamos anteriormente, esse índice é formado por 3 indicadores, e buscaremos analisar cada um destes individualmente:
Para a análise quanto à relação do Covid com índices educacionais de cada município fluminense, utilizaremos o IDEB, Índice de Desenvolvimento da Educação Básica, utilizado para medir o nível das escolas públicas brasileiras em uma escala de 0 a 10 levando em conta o desempenho escolar formal dos estudantes e o chamado fluxo escolar (que leva em conta repetências, evasão escolar, etc.). Essa base é obtida através da Base dos Dados, e realizamos a seguir a obtenção dos dados:
ideb = bd.read_sql(
'''
SELECT id_municipio AS id, sigla_uf, AVG(ideb) AS ideb , ano
FROM basedosdados.br_inep_ideb.municipio
WHERE ano = 2019 AND rede = 'publica'
GROUP BY id_municipio, sigla_uf, ano
''',
billing_project_id='adameplayground')
Realizamos o mesmo processo anterior, filtrando as informações importantes e filtrando o que é necessário (o id maior que 1000, por exemplo, retira ids incorretos, como 0). Fazemos novamente o merge com RJ_data, mas dessa vez podemos utilizar o id, obetendo os dados de geometria.
ideb_data = ideb.astype({"id": int})
ideb_data = ideb_data[ideb_data["id"] > 1000]
ideb_data = ideb_data[(ideb_data["sigla_uf"] == "RJ")].reset_index(drop=True)
RJ_ideb = pd.merge(RJ_data, ideb_data, on='id')
RJ_ideb.head()
Podemos realizar a plotagem geométrica. Note como a distribuição é diferente do próprio IDH, já que a Região Metropolitana, por exemplo, que possuía os valores maiores, não tem um IDEB muito alto. Os melhores índices, na verdade, se concentram na Região Noroeste do estado.
fig = px.choropleth(RJ_ideb,
geojson = RJ_ideb["geom"],
locations = RJ_ideb.index,
color = "ideb",
hover_name = "name",
color_continuous_scale = "Blues",
labels = {
"ideb": "IDEB ",
},
)
fig.update_geos(
projection=dict(
scale=55
),
center = dict(
lat=-22.208333,
lon=-42.896388
)
)
fig.update_layout(
title_text = "IDEB de 2019, por município do RJ",
margin={"r":0,"t":50,"l":0,"b":50}
)
fig.show()
Agora que observamos a diferença de distribuição, temos interesse em analisar se há, ou não, correlação a partir desse índice. Faremos novamente o scatter plot e a linha de tendência, analisando o $R^2$ para observar a própria correlação.
covid_ideb = pd.merge(RJ_ideb, covid_rj, on='id')
fig = px.scatter(covid_ideb, x="death_rate", y="ideb" , hover_data=['name'],
trendline="ols",trendline_color_override="orange",
title="Gráfico de dispersão entre taxa de mortalidade e IDEB",
labels={"death_rate": "Taxa de mortalidade",
"name": "Município",
"ideb":"IDEB"})
fig.show()
O resultado é melhor que o anterior. Visualmente, é possível perceber algum nível de relação entre as variáveis, uma que que o IDEB é menor, a taxa de mortalidade tende a ser menos também. Já o próprio $R^2$ nos indica que essa correlação não pode ser formalmente induzida. O valor, que varia entre 0 e 1, tem uma aumento considerável quando comparado à análise do IDH, mas ainda não é suficiente para podermos dizer que a correlação existe.
Passaremos ao segundo indicador, buscando determinar se há alguma correlação entre este fator e a mortalidade por Covid-19 nos municípios do Rio de Janeiro. Para isso, utilizamos o ADH, Atlas do Desenvolvimento Humano, criado pela ONU, e que tem dentre suas informações a expectativa de vida. O banco de dados utilizado para esta parte também pertence à Base dos Dados, e os obtemos a seguir, utilizando o censo do IBGE mais recente, de 2010:
life_exp = bd.read_sql(
'''
SELECT id_municipio AS id, expectativa_vida
FROM basedosdados.mundo_onu_adh.municipio
WHERE ano = 2010
''',
billing_project_id='adameplayground')
Para isso, fazemos o merge a partir do id com o dataframe espacial, mantendo apenas os do estado do RJ, e fazendo as conversões necessárias.
life_exp['id'] = life_exp['id'].astype('int')
cities_health = pd.merge(RJ_data, life_exp, how='inner', on='id')
rj_health = cities_health[cities_health['sigla_uf'] == 'RJ']
rj_health['id'] = rj_health['id'].astype('int')
rj_health.head()
Agora podemos fazer o gráfico do estado novamente, analisando a expectativa de vida para cada município. Note que esse índice se parece mais com o que havíamos visto do IDH do que o de educação, o que pode nos indicar uma queda na correlação entre os fatores.
fig = px.choropleth(rj_health,
geojson = rj_health["geom"],
locations = rj_health.index,
color = "expectativa_vida",
hover_name = "name",
color_continuous_scale = "Burg",
labels = {
"expectativa_vida": "Expectativa de vida"
}
)
fig.update_geos(
projection=dict(
scale=55
),
center = dict(
lat=-22.208333,
lon=-42.896388
)
)
fig.update_layout(
title_text = "ADH de 2010, por município do RJ",
margin={"r":0,"t":50,"l":20,"b":50}
)
fig.show()
Ainda assim, realizaremos o mesmo processo anterior a partir dos dados de covid e da expectativa de vida.
health_covid_rj = pd.merge(rj_health, covid_rj, how='inner', on='id')
health_covid_rj.head()
Certamente é necessário confirmar a desconfiança que temos de que a correlação será baixa, então faremos a análise a seguir:
fig = px.scatter(health_covid_rj, x="death_rate", y="expectativa_vida", hover_data=['name'], trendline="ols",
color_discrete_sequence=['#FF84DD'],trendline_color_override="orange",
title="Gráfico de dispersão entre taxa de mortalidade e ADH",
labels={"death_rate": "Taxa de mortalidade",
"name": "Município",
"expectativa_vida":"Expectativa de vida"})
fig.show()
Observe que, de fato, os pontos não apresentaram qualquer linearidade ou mesmo indicação de tendência, espalhando-se de forma apararentemente desordenada. A linha de tendência traçada tem o $R^2$ baixíssimo, e mesmo visualmente não parece ser acompanhada pelos pontos do gráfico. Assim, constatamos que o segundo indicador não tem correlação clara com a taxa de mortes por Covid-19 no estado, e passamos ao último indicador para podermos responder à pergunta original.
Avançamos ao terceiro e último parâmetro do IDH. O PIB, Produto Interno Bruto, avalia a soma de todos os bens e serviços finais produzidos, nesse caso, por cada município. Ao fazermos o PIB per Capita, que é o utilizado no cálculo do IDH, dividimos o PIB pela população total de cada cidade do estado. Para tal, utilizamos duas bases do Base dos Dados, uma que continha o PIB e outra com as populações, para efetuarmos esse cálculo:
pib = bd.read_sql(
'''
SELECT id_municipio as id, pib, ano
FROM `basedosdados.br_ibge_pib.municipio`
WHERE ano = 2018
''',
billing_project_id='adameplayground')
pop = bd.read_sql(
'''
SELECT id_municipio as id, populacao as pop
FROM `basedosdados.br_ibge_populacao.municipio`
WHERE ano = 2018 AND sigla_uf = 'RJ'
''',
billing_project_id='adameplayground')
Com isso, foi possível fazermos as conversões necessárias e o cálculo desejado, além do merge com as informações espaciais, possibilitando a plotagem das informações
pib_data = pib.astype({"id": int})
pop_data = pop.astype({"id": int})
pib_data = pd.merge(pib_data, pop_data, on='id')
RJ_pib = pd.merge(RJ_data, pib_data, on='id')
RJ_pib = pd.merge(RJ_pib, covid_rj, on='id')
RJ_pib["per_capita"] = RJ_pib["pib"]/RJ_pib["pop"]
RJ_pib.head()
Na escala de cores, usaremos apenas até o valor de 100k, pois caso usássemos o maior valor outlier (200k), o mapa praticamente inteiro ficaria com cores claras demais, o que explicita a desigualdade do PIB entre os municípios. Veja o mapa a seguir:
fig = px.choropleth(RJ_pib,
geojson = RJ_pib["geom"],
locations = RJ_pib.index,
color = "per_capita",
hover_name = "name",
color_continuous_scale = "Greens",
range_color=(10000, 100000),
labels = {
"per_capita": "PIB per Capita"
},
)
fig.update_geos(
projection=dict(
scale=55
),
center = dict(
lat=-22.208333,
lon=-42.896388
)
)
fig.update_layout(
title_text = "PIB per capita estimado de 2018, por município do RJ",
margin={"r":0,"t":50,"l":20,"b":50}
)
fig.show()
Certamente a visualização nos dá, intuitivamente, uma resposta. A distribuição é desigual demais para que tenhamos esperança de correlação. Municípios como Maricá e São João da Barra têm PIBs per Capita altíssimos, enquanto Belford Roxo, por exemplo, tem cerca de $10\%$ do valor. Mas façamos a plotagem:
fig = px.scatter(RJ_pib, x="death_rate", y="per_capita", hover_data=['name'], trendline="ols",
color_discrete_sequence=['green'],trendline_color_override="orange",
title="Gráfico de dispersão entre taxa de mortalidade e PIB per Capita",
labels={"death_rate": "Taxa de mortalidade",
"name": "Município",
"per_capita":"PIB per Capita"})
fig.show()
De fato, não há correlação estabelecida entre os fatores. A distância inicial no gráfico pode dar indicativo de linearidade, mas aproximando a plotagem (o plotly express permite essa função, teste!), vemos a aleatoriedade entre os pontos. O $R^2$ é muito baixo e, de fato, chegamos a uma conclusão final.
Assim, após analisarmos o próprio IDH e suas três dependências e a relação destes com a pandemia do Covid-19 no estado do Rio de Janeiro, chegamos à conclusao de que não é possível definirmos uma correlação clara entre os fatores, respondendo a pergunta inicial da análise.
Certamente, a evolução da pandemia teve influência de diversos outros fatores, como densidade demográfica (determinando quais são os grandes enchames urbanos que em geram facilitam a propagação do vírus) ou mesmo aspectos políticos que determinam quais medidas serão tomadas para contenção da evolução do cenário. Certamente, passamos ainda por várias ondas, que foram acompanhadas por guinadas no rumo dos grupos sociais mais diretamente envolvidos em cada fase, etc..